"use strict";

window.onload=function()
{
    colorResolutionGame.initiate();
};

var colorResolutionGame=(function()
{
/*成员*/
    var broadcast;
    /**
     * @name 菜单层
     * @type Object
     * @see colorResolutionGame
     */
    var menuLayer=(function()
    {
    /*成员*/
        var part;
        /**
         * @name 显示
         * @type Function
         * @see colorResolutionGame-menuLayer
         */
        var show=function()
        {
            part.style.display="block";
        };
        /**
         * @name 隐藏
         * @type Function
         * @see colorResolutionGame-menuLayer
         */
        var hide=function()
        {
            part.style.display="none";
        };
        /**
         * @name 处理开始点击事件
         * @type Function
         * @see colorResolutionGame-menuLayer
         * @description 事件处理函数
         */
        var handler_startClick=function()
        {
            broadcast.trigger("start");

            hide();
        };
        /**
         * @name 处理重置事件
         * @type Function
         * @see colorResolutionGame-menuLayer
         * @description 事件处理函数
         */
        var handler_reset=function()
        {
            show();
        };

    /*接口*/
        /**
         * @name 初始化
         * @type Function
         * @see colorResolutionGame-menuLayer
         */
        var initiate=function()
        {
            part=document.getElementById("menuLayer");          
            document.getElementById("menuLayer_start").addEventListener("click",handler_startClick);

            broadcast.addListener("reset",handler_reset);
        };

        var module=
        {
            initiate:initiate
        };
        return module;
    })();
    /**
     * @name 游戏层
     * @type Object
     * @see colorResolutionGame
     */
    var gameLayer=(function()
    {
    /*成员*/
        var part; 
        var grade_value;
        var score_value;
        /**
         * @name 等级
         * @type Object
         * @see colorResolutionGame-gameLayer
         */
        var level=(function()
        {
        /*成员*/
            var MaxGrade=7;
            var grade_element;
            var score_element;
            /**
             * @name 设置
             * @type Function
             * @see colorResolutionGame-gameLayer-level
             * @param {int} grade 等级 
             * @param {int} score 分数
             */
            var set=function(grade,score)
            {
                grade_element.innerHTML = "等级： " + grade + " / " + MaxGrade;
                score_element.innerHTML = "分数： " + score  + " / "+ grade_value;
            };

        /*接口*/
            /**
             * @name 初始化
             * @type Function
             * @see colorResolutionGame-gameLayer-level
             */
            var initiate=function()
            {
                grade_element=document.getElementById("gameLayer_grade");
                score_element=document.getElementById("gameLayer_score");
            };
            /**
             * @name 得分
             * @type Function
             * @see colorResolutionGame-gameLayer-level
             */
            var goal=function()
            {
                score_value++;
                if(score_value==grade_value)
                {
                    grade_value++;
                    score_value=0;
                    
                    if(grade_value==MaxGrade)
                    {
                        var result=
                        {
                            grade:grade_value
                        };
                        broadcast.trigger("end",result);

                        return;
                    }
                }

                set(grade_value,score_value);
            };
            /**
             * @name 重置
             * @type Function
             * @see colorResolutionGame-gameLayer-level
             */
            var reset=function()
            {
                grade_value=1;
                score_value=0;
                set(1,0);
            };

            var module=
            {
                initiate:initiate,
                goal:goal,
                reset:reset
            };
            return module;
        })();
        /**
         * @name 盒子组
         * @type Object
         * @see colorResolutionGame-gameLayer
         */
        var boxBlock=(function()
        {
        /*成员*/
            var Margin=4;
            var part;
            var targetIndex;
            /**
             * @name 处理点击事件
             * @type Function
             * @see colorResolutionGame-gameLayer-boxBlock
             * @param {Object} e 事件对象 
             */
            var handler_click=function(e)
            {
                e.preventDefault();

                if(e.target.thisIndex==targetIndex)        //正确
                    level.goal();
                else        //错误
                {
                    var result=
                    {
                        grade:grade_value
                    };
                    broadcast.trigger("end",result);

                    return;
                }

                create();
            };

        /*接口*/
            /**
             * @name 初始化
             * @type Function
             * @see colorResolutionGame-gameLayer-boxBlock
             */
            var initiate=function()
            {
                part=document.getElementById("gameLayer_block");
                addTapListener(part,null,handler_click);
            }; 
            /**
             * @name 创建
             * @type Function
             * @see colorResolutionGame-gameLayer-boxBlock
             */  
            var create=(function()
            {
                var variation=
                [
                    {h:64},
                    {h:32},
                    {h:16},
                    {h:8},
                    {h:4},
                    {h:2},
                    {h:1}
                ];

                return function()
                {
                    part.innerHTML="";
                    var blockWidth=part.offsetWidth;

                    var number=(grade_value+1)*(grade_value+1);
                    var hMajor=Math.floor(Math.random()*360);
                    var sMajor=100;
                    var l=50;
                    var colorMajor="hsl(" + hMajor + "," + sMajor + "%," + l + "%)";     //主色
                    targetIndex=Math.floor(Math.random()*number);
                    var hSingle=(hMajor + variation[grade_value-1].h)%360;
                    var sSingle=sMajor;
                    var colorSingle="hsl(" + hSingle + "," + sSingle + "%," + l + "%)";     //单色

                    for(var i=0;i<number;i++)
                    {
                        var box=document.createElement("div");
                        box.thisIndex=i;
                        box.style.height=box.style.width=blockWidth/(grade_value+1)-Margin*2+"px";
                        box.style.background=(i==targetIndex ? colorSingle : colorMajor);
                        box.className="GameLayer_Box";

                        gameLayer_block.appendChild(box);
                    }
                }   
            })(); 

            var module=
            {
                initiate:initiate,
                create:create
            };
            return module;
        })();
        /**
         * @name 显示
         * @type Function
         * @see colorResolutionGame-gameLayer
         */
        var show=function()
        {
            part.style.display="block";
        };
        /**
         * @name 隐藏
         * @type Function
         * @see colorResolutionGame-gameLayer
         */
        var hide=function()
        {
            part.style.display="none";
        };
        /**
         * @name 开始
         * @type Function
         * @see colorResolutionGame-gameLayer
         */
        var handler_start=function()
        {
            level.reset();
            show();
            boxBlock.create();
        };
        /**
         * @name 结束
         * @type Function
         * @see colorResolutionGame-gameLayer
         * @description 事件处理函数
         */
        var handler_end=function()
        {
            hide();
        };

    /*接口*/
        /**
         * @name 初始化
         * @type Function
         * @see gameResolutionGame-gameLayer
         */
        var initiate=function()
        {
            part=document.getElementById("gameLayer");
            level.initiate();
            boxBlock.initiate();

            broadcast.addListener("start",handler_start);
            broadcast.addListener("end",handler_end);
        };

        var module=
        {
            initiate:initiate
        };
        return module;
    })();
    /**
     * @name 结果层
     * @type Object
     * @see colorResolutionGame
     */
    var resultLayer=(function()
    {
    /*成员*/
        var part;
        var result;
        /**
         * @name 显示
         * @type Function
         * @see colorResolutionGame-resultLayer
         */
        var show=function()
        {
            part.style.display="block";

        };
        /**
         * @name 隐藏
         * @type Function
         * @see colorResolutionGame-resultLayer
         */
        var hide=function()
        {
            part.style.display="none";
        };
        /**
         * @name 结束
         * @type Function
         * @see colorResolutionGame-resultLayer
         * @description 事件处理函数
         */
        var handler_end=function(data)
        {
            result.innerHTML = "等级： " + (data.grade-1);

            show();
        };
        /**
         * @name 处理返回按钮点击事件
         * @type Function
         * @see colorResolutionGame-resultLayer
         * @description 事件处理函数
         */
        var handler_backClick=function(data)
        {
            broadcast.trigger("reset");

            hide();
        };
        

    /*接口*/
        /**
         * @name 初始化
         * @type Function
         * @see colorResolutionGame-resultLayer
         */
        var initiate=function()
        {
            part=document.getElementById("resultLayer");
            result=document.getElementById("resultLayer_result");
            document.getElementById("resultLayer_back").addEventListener("click",handler_backClick);

            broadcast.addListener("end",handler_end);
        }

        var module=
        {
            initiate:initiate
        }
        return module;
    })();

/*接口*/
    /**
     * @name 初始化
     * @type Function
     * @see colorResolutionGame
     */
    var initiate=function()
    {
        broadcast=new Broadcast(["start","end","reset"]);    
        menuLayer.initiate();
        gameLayer.initiate();
        resultLayer.initiate();
    };

    var module=
    {
        initiate:initiate
    };
    return module;
})();

/**
 * @name 添加点击或触摸事件处理函数
 * @description 兼容移动设备
 * @param {Object} node 元素
 * @param {Function} callbackDown 按下鼠标或触摸的回调函数
 * @param {Function} callbackUp 松开鼠标或抬起的回调函数
 */
var addTapListener=(function()      //惰性载入函数
{
    if(window.ontouchstart != undefined)        //兼容移动设备
        return function(node,callbackDown,callbackUp)
        {
            node.addEventListener("touchstart",callbackDown);
            node.addEventListener("touchend",callbackUp);
        };
    else
        return function(node,callbackDown,callbackUp)
        {
            node.addEventListener("mousedown",callbackDown);
            node.addEventListener("mouseup",callbackUp);
        }
})();
/**
 * @name 发布
 */
class Broadcast
{
    /**
     * @name 构造方法
     * @param {Array} keys 事件名数组 
     */
    constructor(keys)
    {
        this.listenerList={};
        for(var i in keys)
            this.listenerList[keys[i]]=[];
    }
    
    /**
     * @name 添加监听者
     * @param {String} key 事件名 
     * @param {Function(Object)} callback 回调函数 
     * @return {boolean} 执行结果
     *      true:成功
     *      false:失败，事件不存在
     */
    addListener(key,callback)
    {
        var methods=this.listenerList[key];
        if(!methods)
            return false;
        else
            methods.push(callback);

        return true;
    }
    /**
     * 
     * @param {String} key 事件名 
     * @param {Object} event 事件数据对象 
     * @return {boolean} 执行结果
     *      true:成功
     *      false:失败，事件不存在
     */
    trigger(key,event)
    {
        var methods=this.listenerList[key];
        if(!methods)
            return false;
        else
            for(var i=0;i<methods.length;i++)
                methods[i](event);

        return true;
    }
}

